using System;
using System.Collections.Generic;
using System.Text;
using MacomberMap.Common.Database_Interface.CIM.Components;
using System.Data;
using MacomberMap.Common.Components;

namespace MacomberMap.Common.Database_Interface.CIM.CIM_Interface
{
    /// <summary>
    /// This class is responsible for handling the opening of a CIM file or index
    /// </summary>
    public abstract class CIM_File_Interface
    {
        #region Abstract methods
        /// <summary>The current position within the CIM file</summary>
        public abstract long Position { get;}

        /// <summary>The size of the CIM file</summary>
        public abstract long FileSize { get;}

        /// <summary>Whether the CIM file has been completely loaded</summary>
        public bool Completed = false;       

        /// <summary>When the processing was first started</summary>
        public DateTime StartTime;

        
        #endregion

        #region Post-load processing
        /// <summary>
        /// Build a list of all elements by their types
        /// </summary>
        public void BuildElementsByType()
        {
            MM_Database_CIM.ElementsByType = new Dictionary<byte, List<CIM_Element>>(MM_Database_CIM.Types.Count);
            for (byte Type = 0; Type < (byte)MM_Database_CIM.Types.Count; Type++)
                MM_Database_CIM.ElementsByType.Add(Type, new List<CIM_Element>());
            foreach (KeyValuePair<MM_rdfID, CIM_Element> Elem in MM_Database_CIM.Elements)
                MM_Database_CIM.ElementsByType[Elem.Value.TypeByte].Add(Elem.Value);            
        }

        /// <summary>
        /// Build the list of type to type mappings
        /// </summary>
        public void BuildTypeToTypes()
        {
            
            for (byte Type = 0; Type < (byte)MM_Database_CIM.Types.Count; Type++)
            {
                //Build our list of outgoing types
                Dictionary<Byte, bool> OutType = new Dictionary<byte, bool>();
                foreach (CIM_Element OutElem in MM_Database_CIM.ElementsByType[Type])
                    foreach (CIM_Element OutLink in OutElem.OutLinks)
                        if (!OutType.ContainsKey(OutLink.TypeByte))
                        {
                            OutType.Add(OutLink.TypeByte, true);
                            List<Byte> InLinks;
                            if (!MM_Database_CIM.TypeFromTypes.TryGetValue(OutLink.TypeByte, out InLinks))
                                MM_Database_CIM.TypeFromTypes.Add(OutLink.TypeByte, InLinks = new List<byte>());
                            if (!InLinks.Contains(Type))
                                InLinks.Add(Type);
                        }
                MM_Database_CIM.TypeToTypes.Add(Type, new List<Byte>(OutType.Keys));
            }

            foreach (List<byte> kvp in MM_Database_CIM.TypeToTypes.Values)
                kvp.TrimExcess();
            foreach (List<byte> kvp in MM_Database_CIM.TypeFromTypes.Values)
                kvp.TrimExcess();
        }
        #endregion
    }
}
